var CodeEditor = Class.create();
CodeEditor.prototype = {
	// Constructor
	initialize: function(id, parameters) {
		// get textarea
		this.textarea = $(id);

		if (this.textarea.tagName.toLowerCase() != 'textarea') {
			return;
		}

		// bind events
	    this.eventKeydown = this._onKeyDown.bindAsEventListener(this);
    	Event.observe(this.textarea, "keydown", this.eventKeydown);
  	},

	_onKeyDown: function(event) {

		if (event.keyCode == Event.KEY_TAB) {
			Event.stop(event);

			var storedScrollTop = this.textarea.scrollTop;

			// non-Moz browsers
			if (document.selection) {

				// VIA: http://the-stickman.com/web-development/javascript/finding-selection-cursor-position-in-a-textarea-in-internet-explorer/				
				var range = document.selection.createRange();
				var stored_range = range.duplicate();

				stored_range.moveToElementText( this.textarea );
				stored_range.setEndPoint( 'EndToEnd', range );

				start = stored_range.text.length - range.text.length;
				end = start + range.text.length;

			// MOZ
			} else {
				start = this.textarea.selectionStart;
				end = this.textarea.selectionEnd;
			}

   			var sel = this.textarea.value.substring(start, end);

   			var charBeforeSelection = (start > 0) ? this.textarea.value.substring(start-1, start) : '';
   			var charAfterSelection = (end < this.textarea.value.length) ? this.textarea.value.substring(end, end+1) : '';
			var singleLineHighlighted = ((start != end) && (charAfterSelection == '' || charAfterSelection == '\n'));

   			// if no text is selected or the selected text is only one line
   			if (!singleLineHighlighted && (start == end || sel.indexOf('\n') == -1) ) {

				if (event.shiftKey) {

					// check for tab before cursor (and remove it)
					if (charBeforeSelection == '\t') {

						// remove tab
						this.textarea.value =
							this.textarea.value.substring(0, start-1) +
							this.textarea.value.substring(start, this.textarea.value.length);

						this.setSelection(this.textarea, start-1, end-1);
					}
				} else {
					// insert tab

					if (document.selection) {
						document.selection.createRange().text = '\t';
					} else {
						this.textarea.value =
							this.textarea.value.substring(0, start)
							+ '\t' +
							this.textarea.value.substring(end, this.textarea.value.length);

						// re-position cursor (only needed for moz)
						this.setSelection(this.textarea, start+1, start+1);
					}
   				}

   			} else {

	   			var lineStart = start;

				// go in reverse to beginning of first line
				while (lineStart > 0 && this.textarea.value.substring(lineStart, lineStart+1) != '\n') {
					lineStart--;
				}

				// get selection
				var textToTab = this.textarea.value.substring(lineStart, end);
				var initialLength = textToTab.length;

				// insert/remove tabs
				if (event.shiftKey) {

					// remove a tab from each line
					textToTab = textToTab.replace(new RegExp(/\n\t/g),'\n');

					// remove starting tab if on first line
					if (lineStart == 0 && textToTab.substring(0,1) == '\t') {
						textToTab = textToTab.substring(1,textToTab.length);
					}
				} else {
					// add at tab to each line
					textToTab = ((lineStart==0) ? '\t' : '') + textToTab.replace(new RegExp(/\n/g),'\n\t');
				}

				// insert newly tabbed text
				this.textarea.value = this.textarea.value.substring(0, lineStart)
					+ textToTab +
					this.textarea.value.substring(end, this.textarea.value.length);

				// calculate new start,end cursor positions
				var newStart = start + ((event.shiftKey) ? -1 : 1);
				var newEnd = end + (textToTab.length - initialLength);

				// reset selection
				this.setSelection(this.textarea, newStart, newEnd);

   			}
			// restore scroll for moz (grr)
			this.textarea.scrollTop = storedScrollTop;
	   	}
  	},
  	
  	setSelection: function(input, start, end) {
		// note: this is only for textareas. all the checking for linebreaks in IE is unnecessary in <input type="text">

		if (document.selection) {

			// need to get number of line breaks from the beginning to start (why? \r maybe)
			var lineBreaksFromBeginningToStart = 0;
			var fromIndex = input.value.indexOf('\n',0);
			while (fromIndex > -1 && fromIndex < start) {
				lineBreaksFromBeginningToStart++;
				fromIndex = input.value.indexOf('\n',fromIndex+1);
			}

			// also need to find the number of breaks in the selection
			var numberOfLineBreaksInSelection = 0;
			fromIndex = input.value.indexOf('\n',start);
			while (fromIndex > -1 && fromIndex < end) {
				numberOfLineBreaksInSelection++;
				fromIndex = input.value.indexOf('\n',fromIndex+1);
			}

			var range = input.createTextRange();
			range.collapse(true);
			range.moveStart('character', start-lineBreaksFromBeginningToStart);
			range.moveEnd('character', end-start-numberOfLineBreaksInSelection);
			range.select();

		} else {
			input.setSelectionRange(start, end);
		}
  	}
};